Skip to content

Write back non-ASCII pantry key when updating#314

Closed
kthenrique wants to merge 2 commits intocooklang:mainfrom
kthenrique:Non-ASCII_pantry_key
Closed

Write back non-ASCII pantry key when updating#314
kthenrique wants to merge 2 commits intocooklang:mainfrom
kthenrique:Non-ASCII_pantry_key

Conversation

@kthenrique
Copy link
Copy Markdown

TOML doesn't support non-ASCII characters in keys. Such keys need to be inside quotes. When a pantry item is removed, the pantry conf is rewritten and need to consider TOML's constraint.

TOML doesn't support non-ASCII characters in keys. Such keys need to be
inside quotes. When a pantry item is removed, the pantry conf is
rewritten and need to consider TOML's constraint.
@dubadub
Copy link
Copy Markdown
Member

dubadub commented Apr 7, 2026

I'm trying to solve the same issue in #313

@claude
Copy link
Copy Markdown

claude bot commented Apr 7, 2026

Code Review

Summary: This PR correctly fixes the bug where non-ASCII pantry keys (e.g. Swedish å, ä, ö) were written back as unquoted bare TOML keys, producing invalid TOML on round-trip.


What's correct

  • Adding || !key.is_ascii() to toml_escape_key is the right fix. TOML bare keys are restricted to ASCII letters, digits, -, and _; anything else requires quoting.
  • The fix is applied consistently in both src/pantry.rs and src/server/handlers/pantry.rs.
  • Multi-line formatting of the condition improves readability.

Issues / observations

1. Incomplete escaping for edge cases

The current escaping wraps in double quotes and only escapes internal ":

format!("\"{}\"", key.replace('"', "\\\""))

This is fine for typical ingredient names, but it doesn't escape backslash (\) itself. A key like foo\bar would produce "foo\bar" which is invalid TOML (backslash starts an escape sequence). Consider:

format!("\"{}\"", key.replace('\\', "\\\\").replace('"', "\\\""))

2. Pre-existing code duplication

toml_escape_key (and write_pantry_item / serialize_pantry_to_toml) is identically duplicated between src/pantry.rs and src/server/handlers/pantry.rs. This PR touches both copies, which is the right thing to do, but the duplication means future fixes need to be applied in two places. Worth noting as a follow-up refactor opportunity.

3. No tests

There are no tests covering non-ASCII round-tripping. Given the fix is a one-liner it's low risk, but a test like assert_eq!(toml_escape_key("smörgås"), "\"smörgås\"") would guard against regression.

4. Related PR #313

PR #313 addresses the same root cause with a more comprehensive approach: it bumps cooklang to 0.18.3 which exposes a pantry::to_toml_string() that delegates TOML serialization to toml_edit, removing ~120 lines of hand-rolled serialization code entirely. If #313 is merged first, this PR would need to be closed or rebased. It may be worth coordinating to avoid duplicate work.


Verdict

The fix is correct for the stated bug. The main concern is the backslash escaping gap. I'd recommend adding the backslash fix and a test before merging, or coordinating with #313 since they solve the same issue.

@claude
Copy link
Copy Markdown

claude bot commented Apr 7, 2026

Code Review

What this PR does

Adds || !key.is_ascii() to toml_escape_key() in both src/pantry.rs and src/server/handlers/pantry.rs, so non-ASCII ingredient names are quoted when written back to the pantry file.

Issues

Incomplete TOML key escaping: TOML bare keys are restricted to [A-Za-z0-9_-]. The existing toml_escape_key() checks for spaces, ., [, and ] — and now non-ASCII — but still misses characters like #, =, \t, ", \, and control characters. Any of those in an ingredient name would produce an invalid TOML file.

Duplicated fix: The same change is applied to two separate copies of toml_escape_key() that live in src/pantry.rs and src/server/handlers/pantry.rs. The two functions were already identical before this PR; they'll diverge again the next time someone patches one and forgets the other.

Superseded by PR #313: PR #313 removes the hand-rolled serialization entirely and delegates to cooklang::pantry::to_toml_string() from the parser library. That approach handles all TOML escaping correctly, removes the duplication, and additionally fixes silent regressions around section ordering and the spurious [general] header. It's the right fix for the underlying problem.

Recommendation

Close this PR in favour of #313, which provides a complete and correct solution to the same issue. If a quick patch is needed in the meantime, the fix here is directionally correct for the non-ASCII case specifically — just be aware of the remaining gaps.

@claude
Copy link
Copy Markdown

claude bot commented Apr 7, 2026

Code Review

This PR adds !key.is_ascii() to toml_escape_key in two files to fix non-ASCII pantry key serialization. The fix is correct and targeted.

Potential Issues

Conflict with PR #313

PR #313 (open, filed yesterday) solves this same bug more comprehensively by upgrading the cooklang dependency to v0.18.4 and delegating all TOML serialization to cooklang::pantry::to_toml_string(). These two PRs will conflict at merge time. Recommend choosing one approach before merging either.

No regression tests

There is no automated test verifying that non-ASCII ingredient names survive a serialize/re-parse round-trip. PR #313 adds four tests covering this scenario, including Swedish characters (smörgås, äpple). Without a test here, the same bug could regress silently.

Incomplete bare-key quoting

TOML bare keys may only contain A-Za-z0-9_-. The existing checks (space, ., [, ]) and this new !is_ascii() check still leave out characters like =, #, :, and '. This was a pre-existing gap, not introduced here, but it is worth noting while touching this function.

Code duplication remains

toml_escape_key (and the surrounding serialization helpers) is copy-pasted between src/pantry.rs and src/server/handlers/pantry.rs. This PR must patch both copies and the same will be true for any future fixes.

Comparison with PR #313

PR #314 (this PR) PR #313
Net lines changed +12 / -2 +19 / -181
Approach Patch hand-rolled serializer Delegate to library
Code duplication Remains Eliminated
New tests None 4 (non-ASCII, ordering)
Ordering preservation Not addressed Handled via IndexMap in library

This PR is a correct minimal fix. PR #313 is the more maintainable long-term solution and is worth considering as the preferred approach.

@kthenrique
Copy link
Copy Markdown
Author

Duplicate of #313

@kthenrique kthenrique closed this Apr 8, 2026
@kthenrique kthenrique deleted the Non-ASCII_pantry_key branch April 9, 2026 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants